using System;
using System.Collections.Generic;
using System.Data;

using System.IO;
using Lizk.SimpleHUD;
using Lizk.WebScraper;
using SharpMedia.Controls;
using System.Linq;
using System.Threading;
using MediaData;

namespace SharpMedia.Pages
{
    internal class EpisodeSelectionPage : MediaPage
    {
        private MediaDataSet.TitlesRow title;

        private HUDLabel show, genres, summary;

        private HUDLabel unavailable, offline, watched;
        private HUDImage unavailableIcon, offlineIcon, watchedIcon;
        private ScraperIcon scraperImage;
        private HUDContainerSimple imageContainer = new HUDContainerSimple();

        private HUDMoveList list;
        private HUDMoveList seasonList;
        private HUDImage selection, titleImage;
        HUDListScroller vScroller;

        private ScraperResult scrapedInfo;

        PlayerPage playerPage;

        private bool showOffline = true, showUnavailable = true, showWatched = true;
        private bool showDisks = false;

        public EpisodeSelectionPage(MediaPage parent, MediaDataSet.TitlesRow title, RectangleS imagePos, SizeS imageSize)
            : base(parent)
        {
            this.title = title;
            InitializeComponents(imagePos, imageSize, null);
        }

        public EpisodeSelectionPage(MediaPage parent, MediaDataSet.TitlesRow title, RectangleS imagePos, SizeS imageSize, MediaDataSet.EpisodesRow selectedEpisode)
            : base(parent)
        {
            this.title = title;
            InitializeComponents(imagePos, imageSize, selectedEpisode);
        }


        void image_ImageSizeChanged(object sender, EventArgs e)
        {
            RectangleS s = HUDImage.ResizeConstrained(true, titleImage.ImageSize.Size, titleImage.Size);
            scraperImage.Bounds = new RectangleS(titleImage.Bounds.Left + s.Right - 42, titleImage.Bounds.Top + s.Bottom - 42, 42, 42);
        }

        private void InitializeComponents(RectangleS imagePos, SizeS imageSize, MediaDataSet.EpisodesRow selectedEpisode)
        {
            if (imageSize == SizeS.Empty) imageSize = new SizeS(1, 1);
            selection = new HUDImage("selection.png");
            selection.MovementSpeed = 8f;
            selection.Size = new SizeS(400, 64);
            Add(selection);


            list = new HUDMoveList/*<HUDMoveList<EpisodeItem>>*/(new SizeS(400, 64), true);
            list.Bounds = new RectangleS(25, 200, Size.Width - 25, Size.Height - 200);
            list.Anchor = Anchor.All;
            Add(list);

            seasonList = new HUDMoveList(new SizeS(400, 64), true);
            seasonList.Bounds = new RectangleS(list.Bounds.Left, list.Bounds.Top - 25, list.Size.Width, 25);
            seasonList.Anchor = Anchor.Top | Anchor.Left | Anchor.Right;
            Add(seasonList);

            // Insert a scrollbar for the list
            HUDListScroller scroller = new HUDListScroller(list)
            {
                Anchor = Anchor.All ^ Anchor.Top,
                Size = new SizeS(list.Size.Width - 25, 25),
                Location = new PointS(list.Bounds.Left, Size.Height - 25 )
            };

            Add(scroller);

            // Insert a scrollbar for the list
            vScroller = new HUDListScroller(new HUDMoveList(SizeS.Empty, false))
            {
                Anchor = Anchor.All ^ Anchor.Left,
                Size = new SizeS(25, list.Size.Height - 25),
                Location = new PointS(Size.Width - 25, list.Bounds.Top)
            };

            Add(vScroller);
            
            string image = SharpMedia.ImageCache.TryGetImagePath(title, "film.png");
            

            imageContainer.Bounds = imagePos;
            imageContainer.Destination = new PointS(250, 10);
            imageContainer.DestinationSize = new PointS(160f / imageSize.Height * imageSize.Width, 160f);
            imageContainer.MovementStopped += new EventHandler(delegate(object o, EventArgs ea)
                                                           {
                                                               show.Fade(255, 6f);
                                                               if(genres != null)
                                                                genres.Fade(255, 6f);
                                                               summary.Fade(255, 6f);
                                                           
                                                               RectangleS s = HUDImage.ResizeConstrained(true, titleImage.ImageSize.Size, titleImage.Size);
                                                               scraperImage.Bounds = new RectangleS(titleImage.Bounds.Left + s.Right - 42, titleImage.Bounds.Top + s.Bottom - 42, 42, 42);
                                                           });
            imageContainer.MovementSpeed = 8f;
            imageContainer.ScaleSpeed = 8f;
            Add(imageContainer);


            titleImage = new HUDImage(image);
            titleImage.Size = imageContainer.Size;
            titleImage.Anchor = Anchor.All;
            titleImage.ImageSizeChanged +=new EventHandler(image_ImageSizeChanged);

            imageContainer.Add(titleImage);


            scraperImage = new ScraperIcon(title);
            scraperImage.Bounds = new RectangleS(imageContainer.Bounds.Right - 40, imageContainer.Bounds.Bottom - 40, 32, 32);
            scraperImage.Alpha = 0;
            imageContainer.Add(scraperImage);

            show = new HUDLabel(title.Name, "tahoma38b");
            show.Bounds = new RectangleS(imageContainer.Destination.X + imageContainer.DestinationSize.X + 15, imageContainer.Destination.Y + 5, Bounds.Width - imageContainer.Destination.X - imageContainer.DestinationSize.X - 15, 40);
            show.Alpha = 0;
            Add(show);

            summary = new HUDLabel(title.Description, "tahoma14b");
            summary.Anchor = Anchor.All ^ Anchor.Bottom;
            summary.Alpha = 0;
            Add(summary);


            scrapedInfo = SharpMedia.ScraperCache.GetResult(title);


            if (scrapedInfo != null && scrapedInfo.Genres.Count > 0)
            {
                genres = new HUDLabel(String.Join(", ", scrapedInfo.Genres.ToArray()), "tahoma20b");
                genres.Bounds = new RectangleS(show.Bounds.Left + 5, show.Bounds.Bottom - 5, show.Bounds.Width - 5, 25);
                genres.Alpha = 0;
                Add(genres);
                summary.Text = scrapedInfo.Summary;
                summary.Bounds = new RectangleS(show.Bounds.Left, genres.Bounds.Bottom + 1, show.Bounds.Width - 5, imageContainer.Destination.Y + imageContainer.DestinationSize.Y - genres.Bounds.Bottom - 1);
            }
            else
            {
                summary.Bounds = new RectangleS(show.Bounds.Left, show.Bounds.Bottom - 5, show.Bounds.Width - 5, 125);
            }


            unavailable = new HUDLabel("Show unavailable", "tahoma14b");
            unavailable.Bounds = new RectangleS(34, 80, 170, 16);
            unavailable.Alignment = Alignment.VCenter;
            Add(unavailable);

            unavailableIcon = new HUDImage(showUnavailable ? "yes.png" : "no.png");
            unavailableIcon.Bounds = new RectangleS(unavailable.Bounds.Left - 20, unavailable.Bounds.Top, 16, 16);
            Add(unavailableIcon);

            offline = new HUDLabel("Show offline", "tahoma14b");
            offline.Bounds = new RectangleS(unavailable.Bounds.Left, unavailable.Bounds.Bottom + 5, unavailable.Bounds.Width, 16);
            offline.Alignment = Alignment.VCenter;
            Add(offline);

            offlineIcon = new HUDImage(showOffline ? "yes.png" : "no.png");
            offlineIcon.Bounds = new RectangleS(offline.Bounds.Left - 20, offline.Bounds.Top, 16, 16);
            Add(offlineIcon);

            watched = new HUDLabel("Show watched", "tahoma14b");
            watched.Bounds = new RectangleS(offline.Bounds.Left, offline.Bounds.Bottom + 5, offline.Bounds.Width, 16);
            watched.Alignment = Alignment.VCenter;
            Add(watched);

            watchedIcon = new HUDImage(showWatched ? "yes.png" : "no.png");
            watchedIcon.Bounds = new RectangleS(watched.Bounds.Left - 20, watched.Bounds.Top, 16, 16);
            Add(watchedIcon);

            lock (SharpMedia.UpdateLockObject)
                if (!SharpMedia.UpdateLock)
                    ListEpisodes();

            list.MoveItems(false);
            if (list.Count > 0)
            {
                UpdateSelection(false);
                selection.Fade(255, 6f);
                if (selectedEpisode != null)
                    Select(selectedEpisode, true);
            }
            else
                selection.Fade(0, 6f);

        }

        protected override void MediaChanged(MediaDataSet changes)
        {
            if (title.RowState == DataRowState.Deleted)
            {
                SharpMedia.Back();
                return;
            }

            
            
            if (genres != null && scrapedInfo != null && scrapedInfo.Genres.Count > 0)
                genres.Text = string.Join(", ", scrapedInfo.Genres.ToArray());
            
            
            
            summary.Text = title.Description;

            titleImage.File = SharpMedia.ImageCache.TryGetImagePath(title, "film.png");

            EpisodeItem selectedItem = SelectedEpisode();
            HUDMoveList cc = null;
            int startIndex = 0;
            if (selectedItem != null)
            {
                cc = (HUDMoveList)selectedItem.Parent;
                startIndex = cc.StartIndex;
            }

            ListEpisodes();
            seasonList.MoveItems(false);
            list.MoveItems(false);


            if (selectedItem != null)
            {
                Select(selectedItem, false);
                list.GetSelectedControl<HUDMoveList>().SetStartIndex(startIndex, false);
            }
            UpdateSelection(false);
        }


        private EpisodeItem GetItem(int column, int row)
        {
            if (column < list.Count && row < list.Get<HUDMoveList>(column).Count)
            {
                return list.Get<HUDMoveList>(column).Get<EpisodeItem>(row);
            }
            return null;
        }


        private HUDMoveList AddColumn(string title)
        {
            HUDLabel seasonLabel = new HUDLabel(title, "tahoma23b");
            seasonLabel.Size = seasonList.ItemSize;
            seasonLabel.Alignment = Alignment.Top;
            seasonLabel.WordBreak = false;
            seasonList.Add(seasonLabel);

            HUDMoveList episodeList = new HUDMoveList(new SizeS(list.ItemSize.Width, 64), false);
            episodeList.Size = new SizeS(list.ItemSize.Width, list.Bounds.Height);
            episodeList.Anchor = Anchor.Left | Anchor.Top | Anchor.Bottom;
            list.Add(episodeList);
            return episodeList;
        }

        int maxEpisode;
        int maxSeason;

        private void ListEpisodes()
        {

            list.Clear();
            seasonList.Clear();

            // get Etc stuff
            // get episodes

            var episodes = from e in title.GetEpisodesRows()
                           orderby e.Season, e.Episode
                           select e;

            var extras = from f in title.GetFilesRows()
                         where f.GetEpisodeFilesRows().Count() == 0
                         orderby f.Path
                         select f;

            if (episodes.Count() > 0)
            {
                maxEpisode = Util.CountDigits(episodes.Max(e => e.Episode));
                maxSeason = Util.CountDigits(episodes.Max(e => e.Season));
            }
            HUDMoveList episodeList = null;

            if (extras.Count() > 0)
            {
                HUDLabel seasonLabel = new HUDLabel("Extras", "tahoma23b");
                seasonLabel.Size = seasonList.ItemSize;
                seasonLabel.Alignment = Alignment.Top;
                seasonLabel.WordBreak = false;
                seasonList.Add(seasonLabel);

                episodeList = new HUDMoveList(new SizeS(list.ItemSize.Width, 64), false);
                episodeList.Size = new SizeS(list.ItemSize.Width, list.Bounds.Height);
                episodeList.Anchor = Anchor.Left | Anchor.Top | Anchor.Bottom;
                list.Add(episodeList);
            }

            foreach (var extra in extras)
            {
                bool offline = !SharpMedia.RootManager.IsOnline(extra.Volume);

                if (offline && !showOffline)
                    continue;

                EpisodeItem item = new EpisodeItem(episodeList.ItemSize, false, showDisks, extra);
                item.OnMouseDown += new EventHandler<MouseEventArgs>(item_OnMouseUp);
                episodeList.Add(item);
            }

            int season = -1;

            foreach (var episode in episodes)
            {
                int fileAmount = episode.GetEpisodeFilesRows().Count();
                bool offline = Util.IsEpisodeOffline(episode);
                if (fileAmount == 0 && !showUnavailable)
                    continue;

                if (offline && !showOffline)
                    continue;

                if (episode.Watched == 1 && !showWatched)
                    continue;

                if (episode.Season != season)
                {
                    //seasonI++;
                    season = episode.Season;
                    
                    if (episodeList != null)
                        episodeList.MoveItems(false);
                    
                    episodeList = new HUDMoveList(new SizeS(list.ItemSize.Width, 64), false);
                    episodeList.Size = new SizeS(list.ItemSize.Width, list.Bounds.Height);
                    episodeList.Anchor = Anchor.Left | Anchor.Top | Anchor.Bottom;
                    list.Add(episodeList);

                    HUDLabel seasonLabel = new HUDLabel(season != 0 ? "Season " + season : "Episodes", "tahoma23b");
                    seasonLabel.Size = seasonList.ItemSize;
                    seasonLabel.Alignment = Alignment.Top;
                    seasonLabel.WordBreak = false;
                    seasonList.Add(seasonLabel);
                }

                EpisodeItem item = new EpisodeItem(episodeList.ItemSize, false, showDisks, episode, maxSeason, maxEpisode);
                item.OnMouseDown += new EventHandler<MouseEventArgs>(item_OnMouseUp);
                episodeList.Add(item);

            }

            vScroller.List = (HUDMoveList)list.OrderByDescending(x => ((HUDMoveList)x).Count).FirstOrDefault();
        }

        void item_OnMouseUp(object sender, HUDControl.MouseEventArgs e)
        {
            EpisodeItem clickedItem = (EpisodeItem)sender;
            if (clickedItem != SelectedEpisode())
                Select(clickedItem, true);
            else
                Command(HUDCommands.Select, null);
        }

        private EpisodeItem SelectedEpisode()
        {
            if (list.Count == 0 || list.SelectedIndex < 0)
                return null;

            if (list.SelectedIndex < list.Count)
            {
                return (EpisodeItem)((HUDMoveList)list[list.SelectedIndex])
                    [((HUDMoveList)list[list.SelectedIndex]).SelectedIndex];
            }
            return null;
        }

        private void Select(EpisodeItem item, bool animate)
        {
            if (item.HasEpisode)
                Select(item.Episode, animate);
            else
                Select(item.File, animate);
        }

        private void Select(MediaDataSet.EpisodesRow episode, bool animate)
        {
            int s = 0, e = 0;
            for (int i = 0; i < list.Count; i++)
            {
                HUDMoveList episodesList = (HUDMoveList)list[i];
                for (int j = 0; j < episodesList.Count; j++)
                {
                    EpisodeItem item = (EpisodeItem)episodesList[j];
                    if (item.HasEpisode && item.Episode.Season <= episode.Season && item.Episode.Episode <= episode.Episode) 
                    {
                        s = i;
                        e = j;
                    }
                }
            }
            list.SetSelectedIndex(s, animate);
            vScroller.List.SetSelectedIndex(e, animate);
            UpdateSelection(animate);
        }

        private void Select(MediaDataSet.FilesRow file, bool animate)
        {
            int s = 0, e = 0;
            for (int i = 0; i < list.Count; i++)
            {
                HUDMoveList episodesList = (HUDMoveList)list[i];
                for (int j = 0; j < episodesList.Count; j++)
                {
                    EpisodeItem item = (EpisodeItem)episodesList[j];
                    if (item.HasEpisode)
                    {
                        var rightFile = (from f in item.Episode.GetEpisodeFilesRows()
                                    where f.FilesRowParent == file
                                    select f.FilesRowParent).FirstOrDefault();

                        if (rightFile != null)
                        {
                            s = i;
                            e = j;
                        }
                    }
                    else
                    {
                        if (item.File == file)
                        {
                            s = i;
                            e = j;
                        }
                    }
                }
            }
            list.SetSelectedIndex(s, animate);
            vScroller.List.SetSelectedIndex(e, animate);
            UpdateSelection(animate);
        }
       

        private void UpdateSelection(bool animate)
        {
            if (list.Count == 0)
                return;

            HUDMoveList currentList = ((HUDMoveList)list[list.SelectedIndex]);

            if (vScroller.IsDragging && currentList != vScroller.List && (currentList.SelectedIndex != vScroller.List.SelectedIndex || currentList.StartIndex != vScroller.List.StartIndex))
            {
                int modifier = Math.Sign(list.IndexOf(vScroller.List) - list.IndexOf(currentList));
                while (currentList != vScroller.List && (currentList.StartIndex != vScroller.List.StartIndex || currentList.SelectedIndex != vScroller.List.SelectedIndex))
                {
                    currentList.SetIndices(vScroller.List.StartIndex, vScroller.List.SelectedIndex, true);
                    if (currentList.SelectedIndex != vScroller.List.SelectedIndex || currentList.StartIndex != vScroller.List.StartIndex)
                    {
                        list.SelectedIndex += modifier;
                        currentList = ((HUDMoveList)list[list.SelectedIndex]);
                    }
                }
            }
            else if(!vScroller.IsDragging && vScroller.List.SelectedIndex != currentList.SelectedIndex)
            {
                currentList.SelectedIndex = vScroller.List.SelectedIndex;
            }



            seasonList.SetIndices(list.StartIndex,list.SelectedIndex, animate);
            foreach (HUDMoveList l in list)
            {
                l.SetSelectedIndex(((HUDMoveList)list[list.SelectedIndex]).SelectedIndex, animate);
                l.SetStartIndex(((HUDMoveList)list[list.SelectedIndex]).StartIndex, animate);
            }
            if (animate)
                selection.Destination = new PointS(list.Bounds.Left + list.Selection.Left, list.Bounds.Top + list[list.SelectedIndex].Bounds.Top + ((HUDMoveList)list[list.SelectedIndex]).Selection.Top);
            else
                selection.Destination = selection.Location = new PointS(list.Bounds.Left + list.Selection.Left, list.Bounds.Top + list[list.SelectedIndex].Bounds.Top + ((HUDMoveList)list[list.SelectedIndex]).Selection.Top);
        }

        public override void Update(TimeSpan ts)
        {
            base.Update(ts);
            if(list != null)
                UpdateSelection(true);

        }

        public override void Command(HUDCommands command, object tag)
        {
            EpisodeItem currentRow = SelectedEpisode();

            switch (command)
            {
                case HUDCommands.Up:
                    if (list.Count == 0)
                        break;
                    vScroller.List.SelectedIndex--;
                    UpdateSelection(true);
                    break;
                case HUDCommands.Down:
                    if (list.Count == 0)
                        break;
                    vScroller.List.SelectedIndex++;
                    UpdateSelection(true);

                    break;
                case HUDCommands.Left:
                    if (list.Count == 0)
                        break;
                    list.SelectedIndex--;
                    seasonList.SelectedIndex--;
                    UpdateSelection(true);

                    break;
                case HUDCommands.Right:
                    if (list.Count == 0)
                        break;
                    list.SelectedIndex++;
                    seasonList.SelectedIndex++;
                    UpdateSelection(true);
                    break;
                case HUDCommands.PageUp:
                    if (list.Count == 0)
                        break;
                    vScroller.List.SelectedIndex -= 10;
                    UpdateSelection(true);
                    break;
                case HUDCommands.PageDown:
                    if (list.Count == 0)
                        break;
                    vScroller.List.SelectedIndex += 10;
                    UpdateSelection(true);
                    break;
                case HUDCommands.Select:
                    if (currentRow == null)
                        break;

                    if (currentRow.HasEpisode && Util.IsEpisodeOffline(currentRow.Episode))
                        break;
                    if (!currentRow.HasEpisode && !SharpMedia.RootManager.IsOnline(currentRow.File.Volume))
                        break;

                    SharpMedia.Engine.Wait();
                    VideoList vl = new VideoList();


                    var epFiles = from f in title.GetFilesRows()
                                  where SharpMedia.RootManager.IsOnline(f.Volume)
                                  orderby (f.GetEpisodeFilesRows().Count() > 0 ? f.GetEpisodeFilesRows().Min(x => x.EpisodesRow.Season) : 0), (f.GetEpisodeFilesRows().Count() > 0 ? f.GetEpisodeFilesRows().Min(x => x.EpisodesRow.Episode) : 0), f.Path
                                  select f;

                    foreach (var file in epFiles)
                    {
                        var episodes = file.GetEpisodeFilesRows();


                        if (episodes.Length == 0)
                        {
                            vl.Add(new VideoSource(file.TitlesRow.Name + ": " + Path.GetFileName(file.Path), Util.GetDBFilePath(file)));
                        }
                        else
                        {
                            string name = string.IsNullOrEmpty(episodes.First().EpisodesRow.Name) ? "Unknown Title" : episodes.First().EpisodesRow.Name;
                            int season = episodes.First().EpisodesRow.Season;
                            int maxEp = episodes.Max(x => x.EpisodesRow.Episode);
                            int minEp = episodes.Min(x => x.EpisodesRow.Episode);

                            string episode = maxEp == minEp ? minEp.ToString().PadLeft(maxEpisode, '0') : minEp.ToString().PadLeft(maxEpisode, '0') + "-" + maxEp.ToString().PadLeft(maxEpisode, '0');

                            string episodeString;

                            if (season == 0)
                            {
                                episodeString = string.Format("Episode {0}", episode);
                            }
                            else
                            {
                                episodeString = string.Format("{0}x{1}", season, episode);
                            }
                            vl.Add(new VideoSource(file.TitlesRow.Name + " - " + episodeString + ": " + name, Util.GetDBFilePath(file)));


                        }



                        if ((currentRow.HasEpisode && currentRow.Episode.GetEpisodeFilesRows().Any(x => x.FilesRowParent == file)) || (!currentRow.HasEpisode && file == currentRow.File))
                        {
                            vl.SelectedIndex = vl.Count - 1;
                        }
                    }



                    playerPage = new PlayerPage(this, vl);
                    playerPage.FadingStopped += new EventHandler(playerPage_FadingStopped);
                    SharpMedia.Navigate(playerPage);
                    SharpMedia.Engine.Resume();
                    break;
                case HUDCommands.Back:

                    SharpMedia.Back();
                    break;
                case HUDCommands.Menu:
                    if (list.Count == 0)
                        return;
                    lock (SharpMedia.UpdateLockObject)
                    {
                        if (SharpMedia.UpdateLock)
                            return;

                        int priorCount = -1, count = 0, attempts = 0;


                        foreach (HUDMoveList sublist in list)
                            count += sublist.Count;
                        priorCount = count;
                        while ((count == 0 || count == priorCount) && attempts++ < 4)
                        {
                            priorCount = count;
                            if (showUnavailable && showOffline && showWatched)
                            {
                                showUnavailable = false;
                            }
                            else if (!showUnavailable && showOffline && showWatched)
                            {
                                showOffline = false;
                            }
                            else if (!showUnavailable && !showOffline && showWatched)
                            {
                                showWatched = false;
                            }
                            else if (!showUnavailable && !showOffline && !showWatched)
                            {
                                showUnavailable = showWatched = showOffline = true;
                            }
                            SharpMedia.Engine.Wait();
                            ListEpisodes();
                            SharpMedia.Engine.Resume();
                            count = 0;
                            foreach (HUDMoveList sublist in list)
                                count += sublist.Count;
                        }
                        unavailableIcon.File = showUnavailable ? "images/yes.png" : "images/no.png";
                        offlineIcon.File = showOffline ? "images/yes.png" : "images/no.png";
                        watchedIcon.File = showWatched ? "images/yes.png" : "images/no.png";
                        Select(currentRow, false);
                    }
                    break;
                case HUDCommands.Preset1:
                    SetWatched();
                    break;
                case HUDCommands.Preset2:
                    showDisks = !showDisks;
                    for (int i = 0; i < list.Count; i++)
                    {
                        for (int j = 0; j < list.Get<HUDContainer>(i).Count; j++)
                        {
                            EpisodeItem itam = list.Get<HUDContainer>(i).Get<EpisodeItem>(j);


                            if (showDisks)
                                itam.ShowVolumes = true;
                            else
                                itam.ShowVolumes = false;
                        }
                    }
                    break;
                case HUDCommands.Web:
                    if(title != null)
                        Util.TryScrape(this, title); 
                    break;
                default:
                    parent.Command(command, tag);
                    break;
            }
        }

        void playerPage_FadingStopped(object sender, EventArgs e)
        {
            if (playerPage.Alpha == 0)
                this.Alpha = 255;
            else
                this.alpha = 0;
        }

        private DateTime lastWatched = DateTime.MinValue;
        private EpisodeItem lastWatchedSelection;
        private void SetWatched()
        {
            TimeSpan ts = DateTime.Now.Subtract(lastWatched);

            if (!SelectedEpisode().HasEpisode)
                return;
            
            

            MediaDataSet.EpisodesRow row = SelectedEpisode().Episode;
            if (ts.TotalMilliseconds <= 500 && lastWatchedSelection == SelectedEpisode())
            {
                ToggleAllWatched(row);
            }
            else
            {
                ToggleWatched(row);
            }
            lastWatchedSelection = SelectedEpisode();
        }

        private void ToggleWatched(MediaDataSet.EpisodesRow episode)
        {
            SharpMedia.WaitForLock();

            episode.Watched = episode.Watched == 0 ? 1 : 0;

            lastWatched = DateTime.Now; 
            SharpMedia.WorkDone();
        }

        private void ToggleAllWatched(MediaDataSet.EpisodesRow episode)
        {
            SharpMedia.WaitForLock();

            var episodes = from e in episode.TitlesRow.GetEpisodesRows()
                           where e.Season < episode.Season || (e.Season == episode.Season && e.Episode <= episode.Episode)
                           select e;

            foreach (var oEp in episodes)
            {
                oEp.Watched = episode.Watched;
            }

            lastWatched = DateTime.MinValue;
            SharpMedia.WorkDone();
        }


        #region pagenavigation

        public override void Close()
        {
            Fade(0, 6f);
        }

        public override void Deactivate()
        {
        }

        public override void Show()
        {
            Fade(255, 6f);
        }

        public override void Activate()
        {
            Fade(255, 6f);
            if (playerPage != null)
            {
                MediaDataSet.FilesRow file = Util.GetDBFileFromPath(playerPage.PlaybackList.SelectedItem.File);
                if(file != null)
                    Select(file, true);
            }
        }

        #endregion

        private class EpisodeItem : HUDContainerSimple
        {
            private bool offline, selected, watched, disks;
            private SizeS itemSize;
            private HUDLabel lbl1, lbl2, lbl3;
            private HUDImage icon, selection, watchedIcon;

            public bool Offline
            {
                get 
                {
                    return offline;
                }
                set 
                {
                    offline = value;
                    if (HasEpisode)
                    {
                        if (Episode.GetEpisodeFilesRows().Count() > 0)
                        {
                            icon.File = "harddisk.png";
                            icon.Color = offline ? ColorS.Red : ColorS.White;
                        }
                        else
                        {
                            icon.File = "no.png";
                            icon.Color = ColorS.White;
                        }
                    }
                    else
                    {
                        icon.File = "harddisk.png";
                        icon.Color = offline ? ColorS.Red : ColorS.White;
                    }
                }
            }

            public bool ShowVolumes
            {
                get
                {
                    return disks;
                }
                set
                {
                    disks = value;
                    if(HasEpisode)
                        lbl3.Fade((byte)((offline && Episode.GetEpisodeFilesRows().Count() > 0) || disks ? 255 : 0), 6f);
                    else
                        lbl3.Fade((byte)(offline || disks ? 255 : 0), 6f);
                }
            }

            public bool Watched
            {
                get
                {
                    return watched;
                }
                set
                {
                    watched = value;
                    watchedIcon.Fade(watched ? (byte)255 : (byte)0, 6f);
                }
            }

            public MediaDataSet.EpisodesRow Episode { get; set; }
            public MediaDataSet.FilesRow File { get; set; }

            int maxSeason, maxEpisode;

            public bool HasEpisode { get { return Episode != null; } }

            public EpisodeItem(SizeS itemSize, bool selected, bool disks, MediaDataSet.FilesRow file)
            {
                this.selected = selected;
                this.itemSize = itemSize;
                File = file;
                InitalizeControls();
                ShowVolumes = disks;
                Offline = !SharpMedia.RootManager.IsOnline(file.Volume);
            }
            public EpisodeItem(SizeS itemSize, bool selected, bool disks, MediaDataSet.EpisodesRow episode, int maxSeason, int maxEpisode)
            {
                this.selected = selected;
                this.itemSize = itemSize;
                Episode = episode;
                this.maxEpisode = maxEpisode;
                this.maxSeason = maxSeason;

                watched = Episode.Watched == 1;

                InitalizeControls();
                Offline = Util.IsEpisodeOffline(episode);
                ShowVolumes = disks;

                
            }

            private void InitalizeControls()
            {
                string title, episode, volumes = "";
                if (!HasEpisode)
                {
                    title = "Unknown Title";
                    episode = Path.GetFileName(File.Path);
                    volumes = File.Volume;
                }
                else
                {
                    
                    if (Episode.Season == 0)
                    {
                        episode = string.Format("Episode {0}", Episode.Episode.ToString().PadLeft(maxEpisode, '0'));
                    }
                    else
                    {

                        episode = string.Format("{0}x{1}", Episode.Season.ToString().PadLeft(maxSeason, ' '), Episode.Episode.ToString().PadLeft(maxEpisode, '0'));
                    }

                    
                    if (string.IsNullOrEmpty(Episode.Name))
                    {
                        title = "Unknown Title";
                    }
                    else
                    {
                        title = Episode.Name;
                    }

                    if (Episode.GetEpisodeFilesRows().Count() > 0)
                    {
                        volumes = string.Join(", ", Util.GetEpisodeVolumes(Episode)); //row.GetChildRows("episodeFile")[0]["volume"].ToString();
                    }
                }

                Size = itemSize;
                selection = new HUDImage("selection.png");
                selection.MovementSpeed = 8f;
                selection.Size = new SizeS(400, 64);
                selection.Alpha = selected ? 255 : 0;
                Add(selection);

                lbl1 = new HUDLabel(title, "tahoma20b");//new Font("tahoma", 13f, FontStyle.Bold));
                lbl1.Bounds = new RectangleS(66, 7, itemSize.Width - 66, 22);
                lbl1.Alignment = Alignment.Top | Alignment.Left;
                lbl1.WordBreak = false;
                lbl1.CharacterOffset = new PointS(0, -2);
                Add(lbl1);

                lbl2 = new HUDLabel(episode, "tahoma23b");//new Font("tahoma", 12f, FontStyle.Bold));
                lbl2.Bounds = new RectangleS(70, 29, itemSize.Width - 70, 23);
                lbl2.Alignment = Alignment.Top | Alignment.Left;
                lbl2.WordBreak = false;
                lbl2.CharacterOffset = new PointS(0, -5);
                Add(lbl2);

                lbl3 = new HUDLabel(volumes, "tahoma12b");
                lbl3.Bounds = new RectangleS(66, 48, itemSize.Width - 70, 15);
                lbl3.Alignment = Alignment.Top | Alignment.Left;
                lbl3.WordBreak = false;
                lbl3.CharacterOffset = new PointS(0, -5);
                lbl3.Alpha = 0;
                Add(lbl3);

                icon = new HUDImage("harddisk.png");
                icon.Size = new SizeS(64, 64);
                icon.FadeOnLoad = false;
                Add(icon);

                watchedIcon = new HUDImage("yes.png");
                watchedIcon.Location = new SizeS(32, 32);
                watchedIcon.Size = new SizeS(32, 32);
                watchedIcon.Alpha = watched ? 255 : 0;
                Add(watchedIcon);

            }

            public override void Update(TimeSpan ts)
            {
                base.Update(ts);
                if (!SharpMedia.Engine.IsCursorHidden && IsMouseOver)
                {
                    selection.Fade(200, 6f);
                }
                else
                {
                    selection.Fade(0, 6f);
                }

                if (Episode != null && watched != (Episode.Watched != 0))
                    Watched = Episode.Watched != 0;

            }
        }
    }
}